#ifndef APP_SIGNWAY_KERNEL_H
#define APP_SIGNWAY_KERNEL_H
#include <string>
#include <vector>
#include <unistd.h>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

/*
 * Divide positive or negative dividend by positive or negative divisor
 * and round to closest integer. Result is undefined for negative
 * divisors if the dividend variable type is unsigned and for negative
 * dividends if the divisor variable type is unsigned.
 */
#define DIV_ROUND_CLOSEST(x, divisor) ({   \
    decltype((x)) __x = x;                 \
    decltype((divisor)) __d = divisor;     \
    (((__x) > 0) == ((__d) > 0))           \
        ? (((__x) + ((__d) / 2)) / (__d))  \
        : (((__x) - ((__d) / 2)) / (__d));})

/*
 * Divide positive or negative dividend by positive or negative divisor
 * and march to closest integer. Result is undefined for negative
 * divisors if the dividend variable type is unsigned and for negative
 * dividends if the divisor variable type is unsigned.
 */
#define DIV_MARCH_CLOSEST(x, divisor) ({   \
    decltype((x)) __x = x;                 \
    decltype((divisor)) __d = divisor;     \
    (((__x) > 0) == ((__d) > 0))           \
        ? (((__x) + ((__d) - 1)) / (__d))  \
        : (((__x) - ((__d) - 2)) / (__d));})

#define roundup(x, y) ({             \
    decltype((y)) __y = y;           \
    (((x) + (__y - 1)) / __y) * __y;})

#define rounddown(x, y) ({  \
    decltype((x)) __x = (x);\
    __x - (__x % (y));})

#define min_t(x, y) ({      \
    decltype((x)) _x = (x); \
    decltype((y)) _y = (y); \
    void (&_x == & _y);     \
    _x < _y ? _x : _y; })   \

#define max_t(x, y) ({      \
    decltype((x)) _x = (x); \
    decltype((y)) _y = (y); \
    void (&_x == & _y);     \
    _x > _y ? _x : _y; })   \

#define swap_t(x, y) do {    \
    auto& _x = (x);          \
    auto& _y = (y);          \
    void (&_x == & _y);      \
    auto _tmp = _x;          \
    _x = _y;                 \
    _y = _tmp;               \
} while(0)

/* 环形减一 */
#define cycle_down(pos, sum) ({   \
    decltype((pos)) _pos = (pos); \
    decltype((sum)) _sum = (sum); \
    (_pos + _sum - 1) % _sum;}) 

/* 环形加一 */
#define cycle_up(pos, sum) ({     \
    decltype((pos)) _pos = (pos); \
    decltype((sum)) _sum = (sum); \
    (_pos + 1) % _sum;}) 

/* 环形减n */
#define cycle_down_n(pos, n, sum) ({                      \
    decltype((pos)) _pos = (pos);                         \
    decltype((sum)) _sum = (sum);                         \
    decltype((n)) _n = (n);                               \
    decltype((n) / (sum) + 1) _n_sum = ((n) / (sum) + 1); \
    (_pos + (_sum * _n_sum) - _n) % (_sum);}) 

/* 环形加n */
#define cycle_up_n(pos, n, sum) ({ \
    decltype((pos)) _pos = (pos);  \
    decltype((sum)) _sum = (sum);  \
    decltype((n)) _n = (n);        \
    (_pos + _n) % (_sum);}) 

/* 允许环形减一 */
#define allow_cycle_down(pos, sum, pressing_cnt) ({          \
    decltype((pos)) _pos = (pos);                            \
    decltype((sum)) _sum = (sum);                            \
    decltype((pressing_cnt)) _pressing_cnt = (pressing_cnt); \
    (_pos != 0 || pressing_cnt == 1);})

/* 允许环形加一 */
#define allow_cycle_up(pos, sum, pressing_cnt) ({            \
    decltype((pos)) _pos = (pos);                            \
    decltype((sum)) _sum = (sum);                            \
    decltype((pressing_cnt)) _pressing_cnt = (pressing_cnt); \
    (_pos != (_sum - 1) || pressing_cnt == 1);})

/**
 * clamp - return a value clamped to a given range with strict typechecking
 * @val: current value
 * @lo: lowest allowable value
 * @hi: highest allowable value
 *
 * This macro does strict typechecking of lo/hi to make sure they are of the
 * same type as val.  See the unnecessary pointer comparisons.
 */
#define clamp(val, lo, hi) min_t(max_t(val, lo), hi)

/*
 * abs_t() handles unsigned and signed longs, ints, shorts and chars.  For all
 * input types abs_t() returns a signed long.
 */
#define abs_t(x) ({                   \
    long ret;                         \
    if (sizeof(x) == sizeof(long)) {  \
        long __x = (x);               \
        ret = (__x < 0) ? -__x : __x; \
    } else {                          \
        int __x = (x);                \
        ret = (__x < 0) ? -__x : __x; \
    }                                 \
    ret;                              \
})

/* 执行shell cmd命令并返回结果到resvec */
int32_t myexec(const char *cmd, std::vector<std::string> &resvec);
/* 非堵塞system */
int systemNoBlock(const char * cmdstring);
/* 加载filename到内存 */
bool getFileInfo(const char* filename, std::string& buffer);
/*文件filename更新为buffer*/
bool updateFile(const char* filename, std::string buf);
/* 自动重命名小工具 filename[begin,end]->filename[begin+value,end+value]*/
bool automaticRenamingWidget(const char* srcFileHead, const char* destFileHead, int value);
void check(std::string str, int ret);
void check(std::string str, void* ret, void* errnum);
void set_nonblocking(int fd);/* 设置fd为非堵塞 */
uint8_t *longTouint8_t(long n);
std::string getHexStr(uint8_t *val, int length);
#endif /* APP_SIGNWAY_KERNEL_H */

